
#include "BuscadorCliente.h"
#include <sstream>


BuscadorCliente::BuscadorCliente(int puerto) {
	
	log_buscador.open(LOG_BUSCADOR);
	log_buscador << "Abierto log buscador\n" << flush;
	
	pthread_mutex_init(&mutexClientesPotenciales, NULL);
	pthread_mutex_init(&mutexEstado, NULL);
	
	clientesPotenciales = 0;

	struct sockaddr_in* address = (sockaddr_in*) malloc(sizeof(struct sockaddr_in));
	bzero((char *) address, sizeof(*address));     
	address->sin_family = AF_INET;
	address->sin_addr.s_addr = INADDR_ANY;
	address->sin_port = htons(puerto);

	socketfd = socket(AF_INET, SOCK_STREAM, 0);
	if (socketfd < 0) {
		log_buscador << "Error al abrir el socket principal\n" << flush;
		estado = NoAceptaConexiones;
		return;
	}
	else
		log_buscador << "Socket principal abierto\n" << flush;
		
	if (bind(socketfd, (struct sockaddr*) address, sizeof(*address)) < 0) {
		log_buscador << "Error al hacer el bind del socket\n" << flush;
		estado = NoAceptaConexiones;
		return;		
	}
	
	estado = AceptaConexiones;
	
	log_buscador << "Buscador de clientes inicializado correctamente\n" << flush;
}

BuscadorCliente::~BuscadorCliente() {
	
	log_buscador << "Eliminando buscador de clientes\n" << flush;
	log_buscador.close();
	
}

void BuscadorCliente::ComenzarBusqueda(void* datos, void* BuscarClientes(void*)) {
	
	if (pthread_create (&thread, NULL, BuscarClientes, datos) != 0) {
		log_buscador << "No se puede crear thread principal\n";
		exit (1);
	}
}

int BuscadorCliente::getSocketFd() {
	return socketfd;
}

pthread_t BuscadorCliente::getThread() {
	
	return thread;
}

void BuscadorCliente::setEstado(EstadoBuscador estado) {
	
	pthread_mutex_lock(&mutexEstado);
	this->estado = estado;
	pthread_mutex_unlock(&mutexEstado);
}

EstadoBuscador BuscadorCliente::getEstado() {
	
	pthread_mutex_lock(&mutexEstado);
	EstadoBuscador e = estado;
	pthread_mutex_unlock(&mutexEstado);
	
	return e;
}

int BuscadorCliente::BuscarCliente() {
	
	log_buscador << "Esperando cliente\n" << flush;
	
	while(true) {
	
		struct sockaddr_in* addrCliente;
		socklen_t tamCliente = sizeof(addrCliente);
  
		int cliente = accept(socketfd, (struct sockaddr *) &addrCliente, &tamCliente);
		
		struct timeval timeout;
		timeout.tv_sec = 40;
		timeout.tv_usec = 0;
		setsockopt(cliente, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, sizeof(timeout));
		setsockopt(cliente, SOL_SOCKET, SO_SNDTIMEO, (void *)&timeout, sizeof(timeout));
		
		return cliente;
		
	}
			
}

int BuscadorCliente::getClientesPotenciales() {
	
	pthread_mutex_lock(&mutexClientesPotenciales);
	int n= clientesPotenciales;
	pthread_mutex_unlock(&mutexClientesPotenciales);
	
	return n;
}

void BuscadorCliente::AgregarClientePotencial() {
	
	pthread_mutex_lock(&mutexClientesPotenciales);
	clientesPotenciales++;
	pthread_mutex_unlock(&mutexClientesPotenciales);
	
	log_buscador << "Agregado cliente potencial\n" << flush;
}

void BuscadorCliente::EliminarClientePotencial() {
	
	pthread_mutex_lock(&mutexClientesPotenciales);
	clientesPotenciales--;
	pthread_mutex_unlock(&mutexClientesPotenciales);
	
	log_buscador << "Eliminado cliente potencial\n" << flush;
}

void BuscadorCliente::CrearClientePotencial(void* datos, void* IngresoCliente(void*)) {
	
	pthread_t threadCliente;
	if (pthread_create (&threadCliente, NULL, IngresoCliente, datos) != 0) {
		log_buscador << "No se pudo crear thread para cliente potencial\n" << flush;
	}
	
	AgregarClientePotencial();
}

string BuscadorCliente::CodificarInfoImagenes(vector< infoImagen_t > infoImagenes) {
	
	string mensaje;
	for (unsigned int i=0; i<infoImagenes.size(); i++) {
		
		mensaje += Logger::intToString(infoImagenes.at(i).idImagen) + ";";
		mensaje += infoImagenes.at(i).ruta + ";";
		mensaje += Logger::intToString(infoImagenes.at(i).anchoCuadro) + ";";
		mensaje += Logger::intToString(infoImagenes.at(i).altoCuadro) + ";";
		mensaje += Logger::intToString(infoImagenes.at(i).cantCuadros) + ";";
		mensaje += Logger::intToString(infoImagenes.at(i).angulo) + ";";
		mensaje += Logger::intToString(infoImagenes.at(i).espejar) + ";";
		mensaje += "#";
	}
	
	return "<" + mensaje + ">";
}

string BuscadorCliente::CodificarInfoSonidos(vector< infoSonido_t > infoSonidos) {
	
	string mensaje;
	for (unsigned int i=0; i<infoSonidos.size(); i++) {
		
		mensaje += Logger::intToString(infoSonidos.at(i).idSonido) + ";";
		mensaje += Logger::intToString(infoSonidos.at(i).tipo) + ";";
		mensaje += infoSonidos.at(i).ruta + ";";
		mensaje += "#";
	}
	
	return "<" + mensaje + ">";
}

string BuscadorCliente::CodificarPersonajesHabilitados(vector< pair<int, TipoPersonaje*> > personajes) {
	
	string mensaje;
	
	for (unsigned int i=0; i<personajes.size(); i++) {
		
		mensaje += Logger::intToString(personajes.at(i).first) + ";";
		mensaje += personajes.at(i).second->nombre + ";";
		mensaje += Logger::intToString(personajes.at(i).second->ancho) + ";";
		mensaje += Logger::intToString(personajes.at(i).second->alto) + ";";
		mensaje += Logger::intToString(personajes.at(i).second->velocidad) + ";";
		mensaje += Logger::intToString(personajes.at(i).second->salto) + ";";
		mensaje+=Logger::intToString(personajes.at(i).second->margenScroll)+";";
		
		for (unsigned int k=0; k<personajes.at(i).second->acciones.size(); k++) {
			mensaje += personajes.at(i).second->acciones.at(k).archivo + ";";
			mensaje += Logger::intToString(personajes.at(i).second->acciones.at(k).cuadros) + ";";
		}
		
		mensaje += "#";
	}
		
	return "<" + mensaje + ">";
}
	
